.TITLE DKDRV .IDENT /09/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; VERSION 09 ; ; D. N. CUTLER 19-OCT-73 ; ; PREVIOUSLY MODIFIED BY: ; ; P. J. BEZEREDI ; D. N. CUTLER ; C. A. D'ELIA ; ; MODIFIED BY: ; ; P. J. BEZEREDI 14-DEC-77 ; ; PB050 -- REMOVE UNNEEDED CONDITIONALS FOR RSX-11M+. ; ; P. J. BEZEREDI 21-AUG-78 ; ; PB083 -- ADDITION OF SOFTWARE VOLUME VALID SUPPORT. ; ; P. J. BEZEREDI 06-OCT-78 ; ; PB089 -- MAKE USE OF EXTENDED INSTRUCTION SET. ; ; ; RK11 CARTRIDGE DISK DRIVER ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS ; ; EQUATED SYMBOLS ; RETRY=8. ;ERROR RETRY COUNT ; ; LOCAL DATA ; ; CONTROLLER IMPURE DATA TABLES (INDEXED BY CONTROLLER NUMBER) ; RTTBL: .BLKW R$$K11 ;ERROR RETRY COUNT AND DRIVE RESET FLAG ; ; DIAGNOSTIC FUNCTION TABLE ; FUNTBL: .WORD IO.HMS!IQ.UMD, 0515 .WORD IO.BLS!IQ.UMD, 0511 FUNTB0: .WORD IO.RDH!IQ.UMD, 2505 .WORD IO.WDH!IQ.UMD, 2503 .WORD IO.WCK!IQ.UMD, 0507 FUNTBE: ; ; DRIVER DISPATCH TABLE ; DDT$ DK,R$$K11 ;GENERATE DISPATCH TABLE ;+ ; **-DKINI-RK11 CARTRIDGE DISK CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QUEUE I/O DIRECTIVE WHEN AN I/O REQUE ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPAGATE THE ; TION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, THEN AN A ; IS MADE TO DEQUEUE THE NEXT I/O REQUEST. ELSE A RETURN TO THE CALLER I ; EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL, THEN THE NEXT I/O OPER ; ATION IS INITIATED. A RETURN TO THE CALLER IS THEN EXECUTED. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; OUTPUTS: ; ; IF THE SPECIFIED CONTROLLER IS NOT BUSY AND AN I/O REQUEST IS WA ; ING TO BE PROCESSED, THEN THE REQUEST IS DEQUEUED AND THE I/O OP ; ATION IS INITIATED. ;- .ENABL LSB DKINI: GTPKT$ DK,R$$K11,DKCAN ;GET NEXT I/O PACKET TO PROCESS ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1=ADDRESS OF THE I/O REQUEST PACKET. ; R2=PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3=CONTROLLER INDEX. ; R4=ADDRESS OF THE STATUS CONTROL BLOCK ; R5=ADDRESS OF THE UCB OF THE CONTROLLER TO BE INITIATED. ; ; RK11 CARTRIDGE DISK I/O REQUEST PACKET FORMAT: ; ; WD. 00 -- I/O QUEUE THREAD WORD. ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER. ; WD. 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK. ; WD. 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER. ; WD. 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR TASK HEADE ; WD. 05 -- I/O FUNCTION CODE (IO.RLB OR IO.WLB). ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK. ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK. ; WD. 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 14000 ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE. ; WD. 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER. ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER. ; WD. 14 -- NUMBER OF BYTES TO BE TRANSFERED. ; WD. 15 -- NOT USED. ; WD. 16 -- LOW BYTE MUST BE ZERO AND HIGH BYTE NOT USED. ; WD. 17 -- LOGICAL BLOCK NUMBER OF I/O REQUEST. ; WD. 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. ADRS ELSE NOT USED ; WD. 21 -- DIAGNOSTIC REG. BLK ADRS (REAL OR DISPL.+140000) ; MOV #RETRY&377,RTTBL(R3) ;CLEAR POSITIONING AND SET RETRIES CALL $VOLVD ;VALIDATE VOLUME VALID BCS 8$ ;IF CS WE FAILED TST R0 ;TRANSFER FUNCTION? BMI 1$ ;IF MI YES TST I.PRM+2(R1) ;SIZE THE DISK? BPL 8$ ;IF PL NO ASH #13.,R2 ;POSITION UNIT NUMBER MOV S.CSR(R4),R0 ;RETREIVE CSR ADDRESS MOV R2,6(R0) ;SELECT THE DRIVE MOV R0,R2 ;COPY CSR ADDRESS JMP 130$ ;PASS REGISTERS AND EXIT 1$: ;REF LABEL .IF DF M$$EXT CALL $STMAP ;SET UP UNIBUS MAPPING ADDRESS .ENDC CMPB #IO.HMS/^D<256>,I.FCN+1(R1) ;DIAGNOSTIC FUNCTION? BNE 5$ ;IF NE NO MOV #FUNTBL,R0 ;GET ADDRESS OF FUNCTION TABLE 2$: CMP (R0)+,I.FCN(R1) ;FUNCTION CODE MATCH? BEQ 3$ ;IF EQ YES TST (R0)+ ;BYPASS CONTROLLER CODE CMP #FUNTBE,R0 ;END OF FUNCTION TABLE? BEQ 5$ ;IF EQ YES BR 2$ ;TRY AGAIN 3$: CMP R0,#FUNTB0 ;POSITIONING FUNCTION? BHI 4$ ;IF HI NO INCB RTTBL+1(R3) ;YES, INDICATE POSITIONING OPERATION 4$: BIS (R0),U.BUF(R5) ;SET CONTROLLER FUNCTION BITS BR 10$ ;GO CHECK BLOCK NUMBER 5$: MOV #IE.IFC&377,R0 ;ASSUME ILLEGAL FUNCTION BIS #505,U.BUF(R5) ;ASSUME READ LOGICAL FUNCTION CMPB #IO.RLB/256.,I.FCN+1(R1) ;READ LOGICAL FUNCTION? BHIS 9$ ;IF HIS FUNCTION IS ILLEGAL 8$: JMP 120$ ;EXIT 9$: BEQ 10$ ;IF EQ FUNCTION IS READ LOGICAL SUB #2,U.BUF(R5) ;CONVERT TO WRITE LOGICAL FUNCTION 10$: CALL $BLKCK ;CHECK LOGICAL BLOCK NUMBER CALL $CVLBN ;CONVERT LOGICAL BLOCK NUMBER TST R1 ;WHICH SURFACE? BEQ 15$ ;IF EQ SURFACE 0 BIS #20,R0 ;SET SURFACE 1 BIT 15$: MOVB U.UNIT(R5),R1 ;RETREIVE UNIT NUMBER ASH #13.,R1 ;POSITION UNIT SELECT BITS ASH #5,R2 ;POSITION CYLINDER NUMBER BIS R1,R2 ;MERGE UNIT BITS WITH CYLINDER NUMBER BIS R0,R2 ;MERGE TRK/SEC WITH CYLINDER MOV R2,I.PRM+10(R3) ;SAVE STARTING DISK ADDRESS ; ; INITIATE I/O OPERATION ; 30$: ;REF LABEL .IF DF M$$EXT CALL $MPUBM ;MAP UNIBUS TO TRANSFER .ENDC MOV S.CSR(R4),R2 ;GET ADDRESS OF CSR MOV S.PKT(R4),R1 ;RETRIEVE ADDRESS OF I/O REQUEST PACKET MOVB S.ITM(R4),S.CTM(R4) ;SET CURRENT DEVICE TIMEOUT COUNT ADD #6,R2 ;POINT TO DISK ADDRESS REGISTER MOV I.PRM+10(R1),(R2) ;INSERT DISK ADDRESS MOV U.BUF+2(R5),-(R2) ;INSERT BUFFER ADDRESS MOV U.CNT(R5),-(R2) ;INSERT NUMBER OF BYTES TO TRANSFER ROR (R2) ;CONVERT TO WORD COUNT NEG (R2) ;MAKE NEGATIVE WORD COUNT TST -(R2) ;POINT BACK TO CSR MOV #IE.DNR&377,R0 ;ASSUME DRIVE NOT READY TSTB -4(R2) ;IS DRIVE READY? BMI 31$ ;IF MI YES BITB #US.SPU,U.STS(R5) ;IS DRIVE SPINNING UP? BNE 35$ ;IF NE YES BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC OPERATION? BNE 51$ ;IF NE YES CALL $DVERR ;LOG DEVICE NOT READY JMP 110$ ;FINISH UP 31$: BICB #US.SPU,U.STS(R5) ;RESET DRIVE SPINNING UP CALL $BMSET ;SET I/O ACTIVE BIT IN MAP MOV U.BUF(R5),(R2) ;;;LOAD FUNCTION AND GO ; ; CANCEL I/O OPERATION IS A NOP FOR FILE STRUCTURED DEVICES. ; DKCAN: RETURN ;;;NOP FOR THE RK11 ;+ ; POWERFAIL IS HANDLED VIA THE DEVICE TIMEOUT FACILITY AND ; CAUSES NO IMMEDIATE ACTION ON THE UNIT. THE CURRENT TIMEOUT ; COUNT IS EXTENDED SO THAT IF THE UNIT WAS BUSY IT WILL HAVE ; SUFFICIENT TIME TO SPIN BACK UP. THE NEXT I/O REQUEST TO ANY ; UNIT WILL BE SUSPENDED FOR AT LEAST THE EXTENDED TIMEOUT UNLESS ; THE UNIT IS ALREADY READY. ;- DKPWF: TSTB S.STS(R4) ;IS THE DRIVE CURRENTLY BUSY? BEQ 36$ ;IF EQ NO MOVB #3,S.STS(R4) ;WAIT A MAXIMUM OF 45 SECONDS 35$: MOVB #15.,S.CTM(R4) ;15 SECONDS AT A TIME 36$: BISB #US.SPU,U.STS(R5) ;SET UNIT SPINNING UP RETURN ;+ ; **-$DKINT-RK11 DISK CONTROLLER INTERUPTS ;- INTSE$ DK,PR5,R$$K11 ;;;SAVE REGISTERS AND SET PRIORITY TSTB RTTBL+1(R4) ;;;DRIVE RESET IN PROGRESS? BEQ 50$ ;;;IF EQ NO MOV R4,-(SP) ;;;SAVE CONTROLLER INDEX MOV U.SCB(R5),R4 ;;;GET ADDRESS OF SCB MOV @S.CSR(R4),R4 ;;;GET CONTENTS OF CSR BMI 40$ ;;;IF MI DRIVE RESET ERROR BIT #20000,R4 ;;;DRIVE RESET COMPLETE? BNE 40$ ;;;IF NE YES TST (SP)+ ;;;CLEAN STACK RETURN ;;; 40$: MOV (SP)+,R4 ;;;RESTORE CONTROLLER INDEX 50$: CALL $FORK ;;;CREATE A SYSTEM PROCESS MOV R4,R3 ;COPY CONTROLLER INDEX MOV U.SCB(R5),R4 ;GET ADDRESS OF SCB MOV S.CSR(R4),R2 ;GET ADDRESS OF CSR MOV #IS.SUC&377,R0 ;ASSUME SUCCESSFUL TRANSFER MOV S.PKT(R4),R1 ;GET I/O PACKET ADDRESS BITB #IQ.UMD,I.FCN(R1) ;DIAGNOSTIC FUNCTION EXECUTED? 51$: BNE 130$ ;IF NE YES TST (R2) ;ANY ERRORS? BPL 65$ ;IF PL NO CALL $DVERR ;LOG DEVICE ERROR MOV -2(R2),R1 ;SAVE ERROR STATUS REGISTER 53$: MOV S.PKT(R4),R0 ;GET I/O PACKET ADDRESS BITB #IQ.X,I.FCN(R0) ;INHIBIT RETRIES BNE 80$ ;IF NE YES DECB RTTBL(R3) ;ANY MORE RETRIES? BLE 80$ ;IF LE NO MOV #1,(R2) ;CLEAR CONTROLLER CLRB RTTBL+1(R3) ;CLEAR POSSIBLE DRIVE RESET IN PROGRESS 55$: BIT #110000,R1 ;DRIVE RESET REQUIRED? BEQ 70$ ;IF EQ NO 60$: MOVB #1,RTTBL+1(R3) ;SET DRIVE RESET IN PROGRESS MOVB S.ITM(R4),S.CTM(R4) ;RESET TIMEOUT COUNT MOV S.PKT(R4),R1 ;GET ADDRESS OF I/O PACKET MOV I.PRM+10(R1),6(R2) ;SET PROPER DRIVE NUMBER MOV #515,(R2) ;RESET DRIVE RETURN ; 65$: ASRB RTTBL+1(R3) ;DRIVE RESET IN PROGRESS? BCC 75$ ;IF CC NO 70$: JMP 30$ ;RETRY FUNCTION 75$: BITB #IO.WLC&377,I.FCN(R1) ;WRITE WITH WRITE CHECK? BNE 76$ ;IF NE YES BITB #US.WCK,U.STS(R5) ;WRITE CHECK ENABLED? BEQ 110$ ;IF EQ NO 76$: MOV U.BUF(R5),R1 ;GET CURRENT FUNCTION CODE BIT #1*2,R1 ;WRITE OR WRITE CHECK FUNCTION? BEQ 110$ ;IF EQ NO BIS #2*2,U.BUF(R5) ;SET WRITE CHECK FUNCTION BIT #2*2,R1 ;WAS FUNCTION A WRITE CHECK? BNE 110$ ;IF NE YES MOV #RETRY&377,RTTBL(R3) ;REINITIALIZE RETRY COUNT BR 70$ ;START WRITE CHECK OPERATION 80$: MOV #IE.WLK&377,R0 ;ASSUME WRITE LOCK ERROR BIT #20000,R1 ;WRITE LOCK ERROR? BNE 110$ ;IF NE YES MOV #IE.WCK&377,R0 ;ASSUME WRITE CHECK ERROR ASR R1 ;GOOD ASSUMPTION? BCS 110$ ;IF CS WRITE CHECK ERROR MOV #IE.VER&377,R0 ;SET UNRECOVERABLE ERROR 110$: MOV 2(R2),R1 ;GET WORDS LEFT TO TRANSFER ASL R1 ;CONVERT TO BYTES LEFT TO TRANSFER ADD U.CNT(R5),R1 ;CALCULATE BYTES ACTUALLY TRANSFERED MOV #1,(R2) ;CLEAR CONTROLLER 120$: MOVB S.CON(R4),R3 ;RETREIVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ;GET FINAL ERROR RETRY COUNT BIS #RETRY*256.,R2 ;MERGE STARTING RETRY COUNT CALL $IODON ;FINISH I/O OPERATION JMP DKINI ;PROCESS NEXT REQUEST ; ; DEVICE TIMEOUT RESULTS IN A CONTROL AND DRIVE RESET FOLLOWED BY THE ; I/O OPERATION BEING REPEATED UNLESS THE OPERATION WAS DIAGNOSTIC. ; TIMEOUTS ARE USUALLY CAUSED BY POWERFAILURE BUT MAY ALSO BE THE ; RESULT OF A HARDWARE FAILURE. ; DKOUT: BITB #US.SPU,U.STS(R5) ;;;IS DRIVE SPINNING UP? BEQ 125$ ;;;IF EQ NO DECB S.STS(R4) ;;;HAVE WE WAITED ENOUGH YET? BEQ 125$ ;;;IF EQ YES MTPS #0 ;;;ALLOW INTERRUPTS JMP 30$ ; 125$: INCB S.STS(R4) ;;;LEAVE CONTROLLER BUSY BICB #US.SPU,U.STS(R5) ;;;RESET DRIVE SPINNING UP CALL $DTOER ;;;LOG DEVICE TIMEOUT BCC 140$ ;IF CC TIMEOUT DURING NORMAL FUNCTION 130$: CALL $CRPAS ;PASS CONTROLLER REGISTERS TO TASK BR 110$ ;DIAGNOSTIC PROCESSING COMPLETE 140$: MOV #110000,R1 ;SET FOR DRIVE RESET BR 53$ ; .DSABL LSB .END